package com.xuecheng.media.config.threadpool;

import io.micrometer.core.instrument.*;
import io.micrometer.core.instrument.binder.MeterBinder;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.ToDoubleFunction;

@Component
public class ThreadPoolMetrics implements MeterBinder {

    private final ThreadPoolExecutor executor;
    private final String poolName;

    // 使用静态内部类替代 record
    @AllArgsConstructor
    @Getter
    @ToString
    private static final class MetricMeta {
        private final String key;
        private final ToDoubleFunction<ThreadPoolExecutor> function;
        private final String description;
    }

    @Autowired
    public ThreadPoolMetrics(ThreadPoolExecutor threadPoolExecutor) {
        this.executor = threadPoolExecutor;
        this.poolName = "media-thread-pool";
    }

    @Override
    public void bindTo(MeterRegistry registry) {
        bindExecutor(registry, executor, poolName);
    }

    // 静态初始化 - 兼容所有 Java 版本
    private static final List<MetricMeta> METRIC_METAS = Arrays.asList(
            new MetricMeta("core", ThreadPoolExecutor::getCorePoolSize, "核心线程数"),
            new MetricMeta("max", ThreadPoolExecutor::getMaximumPoolSize, "最大线程数"),
            new MetricMeta("active", ThreadPoolExecutor::getActiveCount, "活跃线程数"),
            new MetricMeta("size", ThreadPoolExecutor::getPoolSize, "当前线程数"),
            new MetricMeta("queue", e -> e.getQueue().size(), "队列长度"),
            new MetricMeta("completed", ThreadPoolExecutor::getCompletedTaskCount, "已完成任务数"),
            new MetricMeta("task", ThreadPoolExecutor::getTaskCount, "总任务数")
    );
    private void bindExecutor(MeterRegistry registry, ThreadPoolExecutor executor, String poolName) {
        String className = executor.getClass().getSimpleName().toLowerCase();

        METRIC_METAS.forEach(meta ->
                FunctionCounter.builder("executor.pool." + meta.getKey(), executor, meta.getFunction())
                        .tags("pool", poolName, "class", className)
                        .description(meta.getDescription())
                        .register(registry)
        );
    }
}